/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "着色器.h"
#include "底层绘图/底层绘图框架.h"

#include <file_载入保存数据.h>
using namespace std;


#define NV_EXTENSIONS


#include "shaderc/shaderc.hpp"

/*#ifdef _DEBUG 
#pragma comment(lib, "D:/U/DEV/VulkanSDK/Lib/glslangd.lib")
#pragma comment(lib, "D:/U/DEV/VulkanSDK/Lib/glslang-default-resource-limitsd.lib")
#pragma comment(lib, "D:/U/DEV/VulkanSDK/Lib/shadercd.lib")
#pragma comment(lib, "D:/U/DEV/VulkanSDK/Lib/shaderc_combinedd.lib")
#else
#pragma comment(lib, "D:/U/DEV/VulkanSDK/Lib/glslang.lib")
#pragma comment(lib, "D:/U/DEV/VulkanSDK/Lib/glslang-default-resource-limits.lib")
#pragma comment(lib, "D:/U/DEV/VulkanSDK/Lib/shaderc.lib")
#pragma comment(lib, "D:/U/DEV/VulkanSDK/Lib/shaderc_combined.lib")
#endif*/



//#include "SPIRV/GlslangToSpv.h"
//#include <MoltenVKGLSLToSPIRVConverter/GLSLToSPIRVConverter.h>



bool f_bd_GLSLtoSPV(E_着色阶段 阶段, const string code, const string 保存路径) {
	/*shaderc::Compiler 编译器;

	shaderc_shader_kind shaderStage;

	switch (f_vk_get参数布局着色阶段(阶段)) {
	case VK_SHADER_STAGE_VERTEX_BIT:
		shaderStage = shaderc_vertex_shader;
		break;
	case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
		shaderStage = shaderc_tess_control_shader;
		break;
	case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
		shaderStage = shaderc_tess_evaluation_shader;
		break;
	case VK_SHADER_STAGE_GEOMETRY_BIT:
		shaderStage = shaderc_geometry_shader;
		break;
	case VK_SHADER_STAGE_FRAGMENT_BIT:
		shaderStage = shaderc_fragment_shader;
		break;
	case VK_SHADER_STAGE_COMPUTE_BIT:
		shaderStage = shaderc_compute_shader;
		break;
	case VK_SHADER_STAGE_RAYGEN_BIT_NV:
		shaderStage = shaderc_raygen_shader;
		break;
	case VK_SHADER_STAGE_ANY_HIT_BIT_NV:
		shaderStage = shaderc_anyhit_shader;
		break;
	case VK_SHADER_STAGE_TASK_BIT_NV:
		shaderStage = shaderc_task_shader;
		break;
	case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
		shaderStage = shaderc_glsl_closesthit_shader;
		break;
	case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
		shaderStage = shaderc_glsl_callable_shader;
		break;
	case VK_SHADER_STAGE_MESH_BIT_NV:
		shaderStage = shaderc_mesh_shader;
		break;
	default:
		shaderStage = shaderc_spirv_assembly;
		break;
	}

	auto r = 编译器.CompileGlslToSpv(code, shaderStage, 保存路径.c_str());*/

	return true;
}






inline uint32 S_Vk着色器创建参数::f_get着色阶段(uint32 id) {
	switch (m_参数布局[id].m_着色阶段) {
	case E_着色阶段::e_顶点着色:
		return VK_SHADER_STAGE_VERTEX_BIT;

	case E_着色阶段::e_细分控制着色:
		return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;

	case E_着色阶段::e_细分着色:
		return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;

	case E_着色阶段::e_几何着色:
		return VK_SHADER_STAGE_GEOMETRY_BIT;

	case E_着色阶段::e_像素着色:
		return VK_SHADER_STAGE_FRAGMENT_BIT;

	case E_着色阶段::e_计算着色:
		return VK_SHADER_STAGE_COMPUTE_BIT;
	default:
		break;
	}
	return -1;
}

inline uint32 S_Vk着色器创建参数::f_get参数类型(uint32 id) {
	return f_get缓存布局类型(m_参数布局[id].m_参数类型);
	//return -1;
	VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
}


//void f_vkShader_创建着色器(S_Vk着色* shader, std::string path, E_着色阶段 阶段, uint32 id, bool 光追着色创建, uint32 着色ID) {
void f_vkShader_创建着色器(S_Vk着色* shader, const std::vector<uint32>& code, E_着色阶段 阶段, uint32 id, bool 光追着色创建, uint32 着色ID) {
	
	auto* 着色阶段创建信息 = &shader->m_着色阶段创建信息[id];
	(*着色阶段创建信息) = {};
	着色阶段创建信息->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
	着色阶段创建信息->pNext = 0;
	着色阶段创建信息->pSpecializationInfo = 0;
	着色阶段创建信息->pName = "main";


	着色阶段创建信息->stage = (VkShaderStageFlagBits)f_vk_get参数布局着色阶段(阶段);
	

	VkShaderModuleCreateInfo 着色模型创建信息 = {};
	着色模型创建信息.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
	着色模型创建信息.pNext = 0;
	着色模型创建信息.flags = 0;
	着色模型创建信息.codeSize = code.size();
	着色模型创建信息.pCode = code.data();



	VkResult res = vkCreateShaderModule(shader->m_设备, &着色模型创建信息, NULL, &(着色阶段创建信息->module));
	if (res != VK_SUCCESS) {
		std::cout<<"vkCreateShaderModule error:"<< res << std::endl;
	}
	shader->m_光追着色器[id].m_Type = 阶段;


	if (光追着色创建) {
		VkRayTracingShaderGroupCreateInfoKHR 光追着色组{};
		光追着色组.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
		光追着色组.closestHitShader		= VK_SHADER_UNUSED_KHR;
		光追着色组.anyHitShader			= VK_SHADER_UNUSED_KHR;
		光追着色组.intersectionShader	= VK_SHADER_UNUSED_KHR;
		光追着色组.generalShader		= VK_SHADER_UNUSED_KHR;
		switch (阶段) {
			case E_着色阶段::e_光追回调:
			case E_着色阶段::e_光追射线生成:
			case E_着色阶段::e_光追忽略相交:
				光追着色组.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
				光追着色组.generalShader		= 着色ID;
			
				break;
			case E_着色阶段::e_光追最近相交:
				光追着色组.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;
				//光追着色组.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR;
				//光追着色组.closestHitShader		= m_光追着色组创建信息.size();
				光追着色组.closestHitShader		= 着色ID;
				//光追着色组.intersectionShader = E_光追阶段ID::e_光追阶段ID_AABB;
				break;
			
			default:
				return;
		}

		shader->m_光追着色组创建信息表.insert(std::make_pair(阶段, 光追着色组));
	}
}

void f_vkShader_光追着色器组构建(S_Vk着色* shader, E_着色阶段 阶段, uint32 intersectionShader) {
	auto range = shader->m_光追着色组创建信息表.equal_range(阶段);
	
	for (auto it = range.first; it != range.second; ++it) {
		(*it).second.intersectionShader = intersectionShader;
	}
}

void f_vkShader_构建着色器组信息(S_Vk着色* shader) {
	shader->m_光追着色组创建信息.clear();

	for (auto& e : shader->m_光追着色组创建信息表) {
		shader->m_光追着色组创建信息.push_back(e.second);
	}
}

void f_vkShader_销毁着色器(S_Vk着色* shader, uint32 id, bool 光追着色创建) {
	vkDestroyShaderModule(shader->m_设备, shader->m_着色阶段创建信息[id].module, 0);

	if (光追着色创建) {
		//shader->m_光追着色器.erase(shader->m_光追着色器.begin() + id);
		//shader->m_着色阶段创建信息.erase(shader->m_着色阶段创建信息.begin() + id);
		//shader->m_光追着色组创建信息.erase(shader->m_光追着色组创建信息.begin() + id);
	}
}

static void f_shader_DescriptorSetLayoutBinding(VkDevice 设备, S_DescriptorSet& ds,  const std::vector<S_着色器创建参数>& 参数配置, bool 独立统一变量) {
	
	vector<VkDescriptorSetLayoutBinding>	布局绑定;
	vector<VkDescriptorPoolSize>			描述池大小;
	布局绑定.reserve(参数配置.size());
	描述池大小.reserve(参数配置.size());

	for (auto& e : 参数配置) {
		VkDescriptorSetLayoutBinding lb{};

		switch (e.m_参数类型) {
			case E_板载缓存类型::e_IMAGE_Array:
			case E_板载缓存类型::e_SAMPLER_Array: {
				lb.descriptorCount = 64;
				break;
			}
			case E_板载缓存类型::e_光追BVH:
				lb.descriptorCount = 4;
				break;
			case E_板载缓存类型::e_UBO:
				if (独立统一变量) continue;
			default:
				lb.descriptorCount = 1;
				break;
		}

		lb.binding = e.m_绑定位置;
		lb.descriptorType = (VkDescriptorType)f_get缓存布局类型(e.m_参数类型);
		lb.stageFlags = f_vk_get参数布局着色阶段(e.m_着色阶段);
		布局绑定.push_back(lb);

		VkDescriptorPoolSize ps;
		ps.type = lb.descriptorType;
		ps.descriptorCount = 1;
		描述池大小.push_back(ps);
	}
	std::cout << "CreateDescriptorSetLayout" << std::endl;
	ds.m_参数布局 = f_vk_创建着色器参数布局设置(设备, 布局绑定);


	VkDescriptorPoolCreateInfo 描述池创建信息 = {};
	描述池创建信息.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
	描述池创建信息.pNext = 0;
	描述池创建信息.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
	描述池创建信息.maxSets = 2;
	描述池创建信息.poolSizeCount = 描述池大小.size();
	描述池创建信息.pPoolSizes = 描述池大小.data();
	auto res = vkCreateDescriptorPool(设备, &描述池创建信息, 0, &ds.m_描述池);
	if (res != VK_SUCCESS) {
		std::cout << "error : vkCreateDescriptorPool" << res << std::endl;
	}


	VkDescriptorSetAllocateInfo m_描述集列表分配信息 = {};
	m_描述集列表分配信息.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
	m_描述集列表分配信息.pNext = 0;
	m_描述集列表分配信息.descriptorPool = ds.m_描述池;
	m_描述集列表分配信息.descriptorSetCount = 1;
	m_描述集列表分配信息.pSetLayouts = &ds.m_参数布局;

	res = vkAllocateDescriptorSets(设备, &m_描述集列表分配信息, &ds.m_DescriptorSet);
	if (res != VK_SUCCESS) {
		std::cout << "vkAllocateDescriptorSets error" << std::endl;
	}
}


struct S_Vk着色器顶点输入数据参数 : public S_着色顶点输入参数 {

	uint32 f_添加顶点输入配置(S_着色顶点输入参数& 顶点输入配置) {
		m_绑定位置 = 0;
		m_元素大小 = 顶点输入配置.m_元素大小;
		m_输入数据类型 = VK_VERTEX_INPUT_RATE_VERTEX;
		m_数据格式 = E_数据格式::e_F_RGB;

	}
};


S_Vk着色::S_Vk着色(VkDevice& 设备, uint32 阶段数量, string name) :S_着色(name), m_设备(设备) {
	m_着色阶段创建信息.resize(阶段数量);
	m_光追着色器.resize(阶段数量);
}

S_Vk着色::~S_Vk着色() {
	vkDestroyDescriptorPool(m_设备, m_参数池, nullptr);

	for (auto& e : m_着色阶段创建信息) {
		vkDestroyShaderModule(m_设备, e.module, 0);
	}

	for (auto& e : m_参数布局) {
		vkDestroyDescriptorSetLayout(m_设备, e, 0);
	}
	
	vkDestroyPipelineLayout(m_设备, m_线管布局, 0);

	m_DS.clear();
	m_参数布局.clear();
}


void S_Vk着色::f_create布局描述设置(const S_着色器创建配置& 参数, bool 独立统一变量) {
	vector<VkDescriptorSetLayoutBinding>	布局绑定;
	vector<VkDescriptorPoolSize>			描述池大小;
	布局绑定.reserve(参数.m_参数布局.size());
	描述池大小.reserve(参数.m_参数布局.size());

	for (auto& e : 参数.m_参数布局) {
		VkDescriptorSetLayoutBinding lb{};
		
		switch (e.m_参数类型) {
			case E_板载缓存类型::e_IMAGE_Array:
			case E_板载缓存类型::e_SAMPLER_Array: {
				lb.descriptorCount = 64;
				break;
			}
			case E_板载缓存类型::e_光追BVH:
				lb.descriptorCount = 4;
				break;
			case E_板载缓存类型::e_UBO:
				if(独立统一变量) continue;
			default:
				lb.descriptorCount = 1;
				break;
		}

		lb.binding = e.m_绑定位置;
		lb.descriptorType = (VkDescriptorType)f_get缓存布局类型(e.m_参数类型);
		lb.stageFlags = f_vk_get参数布局着色阶段(e.m_着色阶段);
		布局绑定.push_back(lb);

		VkDescriptorPoolSize ps;
		ps.type = lb.descriptorType;
		ps.descriptorCount = 1;
		描述池大小.push_back(ps);
	}
	std::cout << "CreateDescriptorSetLayout" << std::endl;
	m_参数布局.resize(1);
	m_参数布局[0] = f_vk_创建着色器参数布局设置(m_设备, 布局绑定);


	std::cout << "vkCreateDescriptorPool" << std::endl;
	VkDescriptorPoolCreateInfo 描述池创建信息 = {};
	描述池创建信息.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
	描述池创建信息.pNext = 0;
	描述池创建信息.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
	描述池创建信息.maxSets = 1;
	描述池创建信息.poolSizeCount = 描述池大小.size();
	描述池创建信息.pPoolSizes = 描述池大小.data();
	auto res = vkCreateDescriptorPool(m_设备, &描述池创建信息, 0, &m_参数池);
	if (res != VK_SUCCESS) {
		std::cout<<"error : vkCreateDescriptorPool" << res << std::endl;
	}

}

void S_Vk着色::f_init着色参数布局(const S_着色器创建配置& 参数配置, S_结构对象** 布局描述, uint32 布局描述数量) {
	auto res = 0;
	
	std::vector<VkPushConstantRange> 常量区间;
	for (auto& e : 参数配置.m_常量偏移和字节数) {
		常量区间.push_back({
			f_vk_get参数布局着色阶段(e.阶段),
			e.偏移,
			e.字节数
		});
	}

	if (布局描述数量) {
		for (uint32 i = 0; i < 布局描述数量; ++i) {
			S_GPU参数设置描述* layout = (S_GPU参数设置描述*)(布局描述[i]);
			m_参数布局.push_back(layout->m_参数布局);

			m_DS.push_back(layout->m_DescriptorSet);
		}
	}
	else {
		assert(布局描述数量);
		f_create布局描述设置(参数配置);
	}



	VkPipelineLayoutCreateInfo 线管布局创建信息{};
	线管布局创建信息.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
	线管布局创建信息.pNext = 0;
	线管布局创建信息.flags = 0;
	线管布局创建信息.pPushConstantRanges = 常量区间.data();
	线管布局创建信息.pushConstantRangeCount = 常量区间.size();
	线管布局创建信息.pSetLayouts = m_参数布局.data();
	线管布局创建信息.setLayoutCount = m_参数布局.size();

	res = vkCreatePipelineLayout(m_设备, &线管布局创建信息, 0, &m_线管布局);
	if (res != VK_SUCCESS) {
		std::cout<<"vkCreatePipelineLayout"<<std::endl;
	}



	/////////////////////////////////////////////////////////////////
	//                        顶点绑定信息                         //
	/////////////////////////////////////////////////////////////////
	S_Vk着色器创建参数 参数(参数配置);
	//VkVertexInputBindingDescription 顶点绑定信息 = {};
	uint32 顶点输入配置数量 = 参数.f_get输入数量();
	if (顶点输入配置数量) {
		m_顶点绑定信息.resize(顶点输入配置数量);
		m_管线的顶点输入属性描述.resize(顶点输入配置数量);

		uint32 offset = 0;
		for (uint32 i = 0; i < 顶点输入配置数量; ++i) {
			m_管线的顶点输入属性描述[i].location = i;
			m_管线的顶点输入属性描述[i].binding = 0;
			m_管线的顶点输入属性描述[i].format = (VkFormat)f_get数据格式(参数.m_顶点配置[i].m_数据格式);
			m_管线的顶点输入属性描述[i].offset = offset;

			offset += 参数.f_get输入顶点间隔(i);
		}

		m_顶点绑定信息[0].binding = 0;
		m_顶点绑定信息[0].inputRate = (VkVertexInputRate)参数.f_get输入顶点类型(0);
		m_顶点绑定信息[0].stride = offset;



		m_线管顶点输入状态创建信息.vertexBindingDescriptionCount = 1;
		m_线管顶点输入状态创建信息.pVertexBindingDescriptions = m_顶点绑定信息.data();
		m_线管顶点输入状态创建信息.vertexAttributeDescriptionCount = 顶点输入配置数量;
		m_线管顶点输入状态创建信息.pVertexAttributeDescriptions = m_管线的顶点输入属性描述.data();
	}
	else {
		m_线管顶点输入状态创建信息.vertexBindingDescriptionCount = 0;
		m_线管顶点输入状态创建信息.pVertexBindingDescriptions = 0;
		m_线管顶点输入状态创建信息.vertexAttributeDescriptionCount = 0;
		m_线管顶点输入状态创建信息.pVertexAttributeDescriptions = 0;
	}
	//VkPipelineVertexInputStateCreateInfo 线管顶点输入状态创建信息;
	m_线管顶点输入状态创建信息.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
	m_线管顶点输入状态创建信息.pNext = NULL;
	m_线管顶点输入状态创建信息.flags = 0;
	
}

void S_Vk着色::f_构建顶点布局(const std::vector<S_着色顶点输入参数>& 参数配置) {
	uint32 顶点输入配置数量 = 参数配置.size();

	m_线管顶点输入状态创建信息.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
	m_线管顶点输入状态创建信息.pNext = NULL;
	m_线管顶点输入状态创建信息.flags = 0;


	if (顶点输入配置数量) {
		m_顶点绑定信息.resize(顶点输入配置数量);
		m_管线的顶点输入属性描述.resize(顶点输入配置数量);

		uint32 offset = 0;
		for (uint32 i = 0; i < 顶点输入配置数量; ++i) {
			m_管线的顶点输入属性描述[i].location = i;
			m_管线的顶点输入属性描述[i].binding = 0;
			m_管线的顶点输入属性描述[i].format = (VkFormat)f_get数据格式(参数配置[i].m_数据格式);
			m_管线的顶点输入属性描述[i].offset = offset;

			offset += 参数配置[i].m_元素大小;
		}

		m_顶点绑定信息[0].binding = 0;
		m_顶点绑定信息[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
		m_顶点绑定信息[0].stride = offset;


		m_线管顶点输入状态创建信息.vertexAttributeDescriptionCount	= 顶点输入配置数量;
		m_线管顶点输入状态创建信息.pVertexAttributeDescriptions		= m_管线的顶点输入属性描述.data();

		m_线管顶点输入状态创建信息.vertexBindingDescriptionCount	= 1;
		m_线管顶点输入状态创建信息.pVertexBindingDescriptions		= m_顶点绑定信息.data();
	}
	else {
		m_线管顶点输入状态创建信息.vertexBindingDescriptionCount = 0;
		m_线管顶点输入状态创建信息.pVertexBindingDescriptions = 0;
		m_线管顶点输入状态创建信息.vertexAttributeDescriptionCount = 0;
		m_线管顶点输入状态创建信息.pVertexAttributeDescriptions = 0;
	}
}

void S_Vk着色::f_构建管线布局(std::vector<C_DescriptorSetLayout*>& 参数配置, const std::vector<S_常量推送创建参数>& 常量) {
	
	m_管线配置 = 参数配置;
	
	std::vector<VkPushConstantRange> 常量区间;
	for (auto& e : 常量) {
		常量区间.push_back({ f_vk_get参数布局着色阶段(e.阶段), e.偏移, e.字节数 });
	}

	std::vector<VkDescriptorSetLayout> 参数布局;
	for (auto& e : 参数配置) {
		参数布局.emplace_back(dynamic_cast<const C_VkDescriptorSetLayout*>(e)->m_参数布局);
	}


	VkPipelineLayoutCreateInfo 线管布局创建信息{};
	线管布局创建信息.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
	线管布局创建信息.pNext = 0;
	线管布局创建信息.flags = 0;
	线管布局创建信息.pPushConstantRanges = 常量区间.data();
	线管布局创建信息.pushConstantRangeCount = 常量区间.size();
	线管布局创建信息.pSetLayouts = 参数布局.data();
	线管布局创建信息.setLayoutCount = 参数布局.size();

	auto res = vkCreatePipelineLayout(m_设备, &线管布局创建信息, 0, &m_线管布局);
	if (res != VK_SUCCESS) {
		std::cout<<"vkCreatePipelineLayout"<<std::endl;
	}
}

void S_Vk着色::f_initRT着色参数布局(const S_着色器创建配置& 参数配置) {
	std::cout<<"Vulkan init ray DescriptorSetLayout"<<std::endl;
	f_create布局描述设置(参数配置);
}

void S_Vk着色::f_alloc参数设置(S_结构指针* 描述集列表) {
	m_描述集列表分配信息 = {};
	m_描述集列表分配信息.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
	m_描述集列表分配信息.pNext = 0;
	m_描述集列表分配信息.descriptorPool = m_参数池;
	m_描述集列表分配信息.descriptorSetCount = m_参数布局.size();
	m_描述集列表分配信息.pSetLayouts = m_参数布局.data();
	
	auto res = vkAllocateDescriptorSets(m_设备, &m_描述集列表分配信息, (VkDescriptorSet*)描述集列表);
	if (res != VK_SUCCESS) {
		std::cout << "vkAllocateDescriptorSets error" << std::endl;
	}

	for (auto& e : m_参数布局) {
		vkDestroyDescriptorSetLayout(m_设备, e, 0);
	}
	m_参数布局.clear();
}

void S_Vk着色::f_free参数设置(S_结构指针* 描述集列表) {
	auto res = vkFreeDescriptorSets(m_设备, m_参数池, 1, (VkDescriptorSet*)描述集列表);
	assert(res == VK_SUCCESS);
}

void S_Vk着色::f_从文件载入着色器(const S_着色器加载参数& 加载参数, uint8 id, bool 光追着色创建) {
	if (加载参数.path.empty()) {
		f_vkShader_创建着色器(this, 加载参数.code, 加载参数.阶段, id, 光追着色创建, id);
	}
	else {
		auto code = f_file_读SPV文件(加载参数.path);
		f_vkShader_创建着色器(this, code, 加载参数.阶段, id, 光追着色创建, id);
		
	}
}





S_GPU参数设置描述* f_vkShader_创建参数布局(VkDevice 设备, const std::vector<S_着色器创建参数>& 参数配置) {
	S_GPU参数设置描述* GPU布局描述 = (S_GPU参数设置描述*)calloc(1, sizeof(S_GPU参数设置描述));

	vector<VkDescriptorSetLayoutBinding>	布局绑定;
	vector<VkDescriptorPoolSize>			描述池大小;

	布局绑定.reserve(参数配置.size());
	描述池大小.reserve(参数配置.size());

	for (auto& e : 参数配置) {
		VkDescriptorSetLayoutBinding lb{};
		
		switch (e.m_参数类型) {
			case E_板载缓存类型::e_IMAGE_Array:
			case E_板载缓存类型::e_SAMPLER_Array: {
				lb.descriptorCount = (DEF_UI_LayerNum + 1) * 3;
				break;
			}
			case E_板载缓存类型::e_光追BVH:
				lb.descriptorCount = 4;

				break;
			default:
				lb.descriptorCount = 1;
				break;
		}

		lb.binding = e.m_绑定位置;
		lb.descriptorType = (VkDescriptorType)f_get缓存布局类型(e.m_参数类型);
		lb.stageFlags = f_vk_get参数布局着色阶段(e.m_着色阶段);
		布局绑定.push_back(lb);

		VkDescriptorPoolSize ps;
		ps.type = lb.descriptorType;
		ps.descriptorCount = 1;
		描述池大小.push_back(ps);
	}
	GPU布局描述->m_参数布局 = f_vk_创建着色器参数布局设置(设备, 布局绑定);


	//std::cout << "vkCreateDescriptorPool" << std::endl;
	VkDescriptorPoolCreateInfo 描述池创建信息 = {};
	描述池创建信息.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
	描述池创建信息.pNext = 0;
	描述池创建信息.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
	描述池创建信息.maxSets = 1;
	描述池创建信息.poolSizeCount = 描述池大小.size();
	描述池创建信息.pPoolSizes = 描述池大小.data();
	auto res = vkCreateDescriptorPool(设备, &描述池创建信息, 0, &GPU布局描述->m_描述池);
	if (res != VK_SUCCESS) {
		std::cout << "error : vkCreateDescriptorPool" << res << std::endl;
	}


	VkDescriptorSetAllocateInfo m_描述集列表分配信息 = {};
	m_描述集列表分配信息.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
	m_描述集列表分配信息.pNext = 0;
	m_描述集列表分配信息.descriptorPool = GPU布局描述->m_描述池;
	m_描述集列表分配信息.descriptorSetCount = 1;
	m_描述集列表分配信息.pSetLayouts = &(GPU布局描述->m_参数布局);

	res = vkAllocateDescriptorSets(设备, &m_描述集列表分配信息, &GPU布局描述->m_DescriptorSet);
	if (res != VK_SUCCESS) {
		std::cout << "vkAllocateDescriptorSets error" << std::endl;
	}

	return GPU布局描述;
}

void f_vkShader_销毁参数布局(VkDevice 设备, S_GPU参数设置描述* 参数布局) {
	vkDestroyDescriptorSetLayout(设备, 参数布局->m_参数布局, 0);
	vkFreeDescriptorSets(设备, 参数布局->m_描述池, 1, &参数布局->m_DescriptorSet);
}





void f_pipe_着色参数设置创建(S_设备环境& ctx) {
	auto device = f_vk_getDevice(ctx);
	auto& rf = *f_vk_get绘图框架(ctx);
	//auto& fr = *dynamic_cast<S_VK框架*>(&绘图框架);
	
	std::vector<S_着色器创建参数> 参数布局 = {
		{ 3, E_着色阶段::e_顶点着色, E_板载缓存类型::e_None},
	};
	rf.m_管线参数设置_None = f_df_创建着色器参数布局(device, 参数布局, nullptr);



	std::vector<S_着色器创建参数> 布局配置 = {
		{ 10, E_着色阶段::e_像素着色, E_板载缓存类型::e_IMAGE_SAMPLER},
	};
	rf.m_管线参数设置_FS_1Tex = f_df_创建着色器参数布局(device, 布局配置, nullptr);

	布局配置 = {
		{ DEF_binding_L3_ArrayImage, E_着色阶段::e_像素着色, E_板载缓存类型::e_IMAGE_Array},
	};
	rf.m_管线参数设置_FS_ImageArray = f_df_创建着色器参数布局(device, 布局配置, nullptr);

	布局配置 = {
		{ DEF_binding_L4_SampleAA, E_着色阶段::e_像素着色, E_板载缓存类型::e_UBO},
	};
	rf.m_管线参数设置_FS_TAA = f_df_创建着色器参数布局(device, 布局配置, nullptr);

	布局配置 = {
		{ DEF_BINDING_PROJECT, E_着色阶段::e_顶点着色, E_板载缓存类型::e_UBO},
	};
	rf.m_管线参数设置_VS_Proj = f_df_创建着色器参数布局(device, 布局配置, nullptr);

	布局配置 = {
		{ 1, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO},
	};
	rf.m_管线参数设置_VS_Mat4 = f_df_创建着色器参数布局(device, 布局配置, nullptr);

	布局配置 = {
		{ 1, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO},
		{ 2, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO},
	};
	rf.m_管线参数设置_VS_WidgetTranform = f_df_创建着色器参数布局(device, 布局配置, nullptr);

	布局配置 = {
		{ DEF_binding_RectColor, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO},
	};
	rf.m_管线参数设置_VS_WidgetColor = f_df_创建着色器参数布局(device, 布局配置, nullptr);

	布局配置 = {
		{ DEF_binding_ConvexRect, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO},
	};
	rf.m_管线参数设置_VS_WidgetConvexRect = f_df_创建着色器参数布局(device, 布局配置, nullptr);

	布局配置 = {
		//{ DEF_binding_L4_TexID,		E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO },
		{ DEF_binding_L4_TexArray,	E_着色阶段::e_像素着色, E_板载缓存类型::e_SAMPLER_Array },
		{ DEF_binding_L4_TexCube,	E_着色阶段::e_像素着色, E_板载缓存类型::e_SAMPLER_Array },
	};
	rf.m_管线参数设置_FS_Textures = f_df_创建着色器参数布局(device, 布局配置, nullptr);




	布局配置 = {
		{ 0,  E_着色阶段::e_顶点着色 | E_着色阶段::e_计算着色, E_板载缓存类型::e_None},
	};
	rf.m_着色布局设置_None = f_df_创建着色器参数布局(ctx, 布局配置);

	布局配置 = {
		{ 0, E_着色阶段::e_顶点着色, E_板载缓存类型::e_UBO},
	};
	rf.m_着色布局设置_VS_Proj = f_df_创建着色器参数布局(ctx, 布局配置);

	布局配置 = {
		{ 1, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO},
	};
	rf.m_着色布局设置_VS_Mat4 = f_df_创建着色器参数布局(ctx, 布局配置);

	布局配置 = {
		{ 1, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO},
		{ 2, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO},
	};
	rf.m_着色布局设置_VS_WidgetTranform = f_df_创建着色器参数布局(ctx, 布局配置);

	布局配置 = {
		{ DEF_binding_L3_ArrayImage,	E_着色阶段::e_像素着色 | E_着色阶段::e_计算着色, E_板载缓存类型::e_IMAGE_Array},
		{ DEF_binding_L3_ArraySampler,	E_着色阶段::e_像素着色 | E_着色阶段::e_计算着色, E_板载缓存类型::e_SAMPLER_Array},
	};
	rf.m_着色布局设置_Comp_L3_ImageSampleArray = f_df_创建着色器参数布局(ctx, 布局配置);
	//布局配置 = {
	//	{ DEF_binding_L4_TexArray, E_着色阶段::e_计算着色, E_板载缓存类型::e_SAMPLER_Array},
	//};
	//rf.m_着色布局设置_Comp_L4_SampleArray = f_df_创建着色器参数布局(ctx, 布局配置);

	布局配置 = {
		{ DEF_binding_L4_LayerArea,	E_着色阶段::e_像素着色 | E_着色阶段::e_计算着色, E_板载缓存类型::e_UBO},
		{ DEF_binding_L4_SampleAA,	E_着色阶段::e_像素着色 | E_着色阶段::e_计算着色, E_板载缓存类型::e_UBO},
	};
	rf.m_着色布局设置_CFS_L4_LayerArea = f_df_创建着色器参数布局(ctx, 布局配置);

	布局配置 = {
		{ DEF_binding_L4_SampleAA, E_着色阶段::e_像素着色 | E_着色阶段::e_计算着色, E_板载缓存类型::e_UBO},
	};
	rf.m_着色布局设置_CFS_L4_SampleTAA = f_df_创建着色器参数布局(ctx, 布局配置);



	rf.m_场景渲染环境 = new C_场景渲染环境(ctx);


}

void f_pipe_着色线管布局创建(S_设备环境& ctx) {
	auto device = f_vk_getDevice(ctx);
	auto* rf = f_vk_get绘图框架(ctx);


	VkDescriptorSetLayout 参数布局[2]{};

	// 定义 UBO 绑定描述
	VkDescriptorSetLayoutBinding 投影绑定{}; 
	投影绑定.binding = 0;
	投影绑定.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
	投影绑定.descriptorCount = 1;
	投影绑定.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT;
	投影绑定.pImmutableSamplers = nullptr;
	参数布局[0] = f_vk_创建着色器参数布局设置(device, {投影绑定});

	VkDescriptorSetLayoutBinding 变换参数绑定{}; 
	变换参数绑定.binding = 1;
	变换参数绑定.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
	变换参数绑定.descriptorCount = 1;
	变换参数绑定.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT;
	变换参数绑定.pImmutableSamplers = nullptr;
	VkDescriptorSetLayoutBinding 纹理参数绑定{}; 
	纹理参数绑定.binding = 10;
	纹理参数绑定.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
	纹理参数绑定.descriptorCount = 1;
	纹理参数绑定.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT;
	纹理参数绑定.pImmutableSamplers = nullptr;
	参数布局[1] = f_vk_创建着色器参数布局设置(device, {变换参数绑定, 纹理参数绑定});

	VkPipelineLayoutCreateInfo 线管布局创建信息{};
	线管布局创建信息.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
	线管布局创建信息.pNext = 0;
	线管布局创建信息.flags = 0;
	线管布局创建信息.pSetLayouts = 参数布局;
	线管布局创建信息.setLayoutCount = 2;

	auto res = vkCreatePipelineLayout(device, &线管布局创建信息, 0, &((S_2D绘图管线布局集*)(rf->m_2D绘图管线布局集))->m_图像绘制管线布局);
	if (res != VK_SUCCESS) {
		std::cout<<"vkCreatePipelineLayout"<<std::endl;
	}

}

void f_pipe_着色线管布局销毁(S_设备环境& ctx) {
	auto device = f_vk_getDevice(ctx);
	auto* rf = f_vk_get绘图框架(ctx);

	vkDestroyPipelineLayout(device, ((S_2D绘图管线布局集*)(rf->m_2D绘图管线布局集))->m_图像绘制管线布局, nullptr);
}



void f_pipe_销毁着色参数设置(S_设备环境& ctx) {
	auto device = f_vk_getDevice(ctx);
	auto* rf = f_vk_get绘图框架(ctx);

	delete rf->m_场景渲染环境;


	f_vkShader_销毁参数布局(device, (S_GPU参数设置描述*)rf->m_管线参数设置_FS_1Tex);
	f_vkShader_销毁参数布局(device, (S_GPU参数设置描述*)rf->m_管线参数设置_FS_ImageArray);
	f_vkShader_销毁参数布局(device, (S_GPU参数设置描述*)rf->m_管线参数设置_VS_Proj);
	f_vkShader_销毁参数布局(device, (S_GPU参数设置描述*)rf->m_管线参数设置_VS_Mat4);
	f_vkShader_销毁参数布局(device, (S_GPU参数设置描述*)rf->m_管线参数设置_VS_WidgetTranform);
	f_vkShader_销毁参数布局(device, (S_GPU参数设置描述*)rf->m_管线参数设置_VS_WidgetConvexRect);
	f_vkShader_销毁参数布局(device, (S_GPU参数设置描述*)rf->m_管线参数设置_FS_Textures);


}

C_VkDescriptorSetLayout::C_VkDescriptorSetLayout(S_设备环境& ctx, const std::vector<S_着色器创建参数>& 参数布局) {
	auto res = 0;

	m_Device = f_vk_getDevice(ctx);

	vector<VkDescriptorSetLayoutBinding>	布局绑定;
	布局绑定.reserve(参数布局.size());

	for (auto& e : 参数布局) {
		VkDescriptorSetLayoutBinding lb{};

		switch (e.m_参数类型) {
			case E_板载缓存类型::e_IMAGE_Array:
			case E_板载缓存类型::e_SAMPLER_Array: {
				lb.descriptorCount = (DEF_UI_LayerNum + 1) * 3;
				break;
			}
			case E_板载缓存类型::e_光追BVH:
				lb.descriptorCount = 4;

				break;
			default:
				lb.descriptorCount = 1;
				break;
		}

		
		lb.descriptorType	= (VkDescriptorType)f_get缓存布局类型(e.m_参数类型);
		lb.stageFlags		= f_vk_get参数布局着色阶段(e.m_着色阶段);
		lb.binding			= e.m_绑定位置;

		布局绑定.push_back(lb);

		m_descriptorType.push_back(lb.descriptorType);
	}
	m_参数布局 = f_vk_创建着色器参数布局设置(m_Device, 布局绑定);

}

C_VkDescriptorSetLayout::~C_VkDescriptorSetLayout() {
	vkDestroyDescriptorSetLayout(m_Device, m_参数布局, 0);
}




C_VkDescriptorSet::C_VkDescriptorSet(S_着色线管* 着色线管) : C_VkDescriptorSet(着色线管->m_Pipeline, 着色线管->m_Shader) {
	
}

C_VkDescriptorSet::C_VkDescriptorSet(S_管线* 线管, S_着色* 着色) {
	m_线管对象 = 线管;

	S_Vk着色* shader = static_cast<S_Vk着色*>(着色);
	for (auto& dsl : shader->m_管线配置) {
		f_addDescriptorSet(*线管->m_Ctx, *dsl);
	}
	
	m_线管对象->m_线管布局 = (S_结构指针)shader->m_线管布局;
}

C_VkDescriptorSet::C_VkDescriptorSet(S_设备环境& ctx, C_DescriptorSetLayout& layout) {
	f_addDescriptorSet(ctx, layout);
}

C_VkDescriptorSet::~C_VkDescriptorSet() {
	auto device = f_vk_getDevice(*m_线管对象->m_Ctx);

	for (auto& e : m_DescriptorPool) {
		vkDestroyDescriptorPool(device, e, nullptr);
	}
}

void C_VkDescriptorSet::f_addDescriptorSet(S_设备环境& ctx, C_DescriptorSetLayout& layout) {
	auto sl = static_cast<C_VkDescriptorSetLayout*>(&layout);
	auto device = f_vk_getDevice(ctx);

	vector<VkDescriptorPoolSize> 描述池大小;

	for (auto& e : sl->m_descriptorType) {
		VkDescriptorPoolSize ps;
		ps.type = e;
		ps.descriptorCount = 1;
		描述池大小.emplace_back(ps);
	}


	VkDescriptorPoolCreateInfo 描述池创建信息 = {};
	描述池创建信息.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
	描述池创建信息.pNext = 0;
	描述池创建信息.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
	描述池创建信息.maxSets = 1;
	描述池创建信息.poolSizeCount = 描述池大小.size();
	描述池创建信息.pPoolSizes = 描述池大小.data();

	VkDescriptorPool dp;
	auto res = vkCreateDescriptorPool(device, &描述池创建信息, 0, &dp);
	if (res != VK_SUCCESS) {
		std::cout << "error : vkCreateDescriptorPool" << res << std::endl;
	}


	VkDescriptorSetAllocateInfo m_描述集列表分配信息 = {};
	m_描述集列表分配信息.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
	m_描述集列表分配信息.pNext = 0;
	m_描述集列表分配信息.descriptorPool = dp;
	m_描述集列表分配信息.descriptorSetCount = 1;
	m_描述集列表分配信息.pSetLayouts = &sl->m_参数布局;

	VkDescriptorSet ds;
	res = vkAllocateDescriptorSets(device, &m_描述集列表分配信息, &ds);
	if (res != VK_SUCCESS) {
		vkDestroyDescriptorPool(device, dp, nullptr);
		std::cout << "vkAllocateDescriptorSets error" << std::endl;
	}

	m_DescriptorPool.emplace_back(dp);
	m_DS.emplace_back(ds);
}

void C_VkDescriptorSet::f_bind(S_推送常量& push) {
	auto* rt = f_vk_get绘图环境(*m_线管对象->m_Ctx);

	auto bp = VkPipelineBindPoint(m_线管对象->m_管线绑定点);

	vkCmdBindPipeline(rt->m_命令缓存, bp, (VkPipeline)(m_线管对象->m_线管));
	vkCmdBindDescriptorSets(rt->m_命令缓存, bp, VkPipelineLayout(m_线管对象->m_线管布局), 0, m_DS.size(), m_DS.data(), 0, nullptr);

	vkCmdPushConstants(
		rt->m_命令缓存, 
		VkPipelineLayout(m_线管对象->m_线管布局), 
		f_vk_get参数布局着色阶段(push.m_常量推送绑定阶段), 
		0, 
		push.m_常量推送字节大小, 
		push.m_常量推送
	);

}


S_结构对象* f_df_createDescriptorSet(S_设备环境& ctx, C_DescriptorSetLayout& layout) {
	auto device = f_vk_getDevice(ctx);
	auto sl = static_cast<C_VkDescriptorSetLayout*>(&layout);
	

	vector<VkDescriptorPoolSize> 描述池大小;
	for (auto& e : sl->m_descriptorType) {
		VkDescriptorPoolSize ps;
		ps.type = e;
		ps.descriptorCount = 1;
		描述池大小.emplace_back(ps);
	}


	VkDescriptorPoolCreateInfo 描述池创建信息 = {};
	描述池创建信息.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
	描述池创建信息.pNext = 0;
	描述池创建信息.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
	描述池创建信息.maxSets = 1;
	描述池创建信息.poolSizeCount = 描述池大小.size();
	描述池创建信息.pPoolSizes = 描述池大小.data();

	VkDescriptorPool dp;
	auto res = vkCreateDescriptorPool(device, &描述池创建信息, 0, &dp);
	if (res != VK_SUCCESS) {
		std::cout << "error : vkCreateDescriptorPool" << res << std::endl;
	}


	VkDescriptorSetAllocateInfo m_描述集列表分配信息 = {};
	m_描述集列表分配信息.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
	m_描述集列表分配信息.pNext = 0;
	m_描述集列表分配信息.descriptorPool = dp;
	m_描述集列表分配信息.descriptorSetCount = 1;
	m_描述集列表分配信息.pSetLayouts = &sl->m_参数布局;

	VkDescriptorSet ds;
	res = vkAllocateDescriptorSets(device, &m_描述集列表分配信息, &ds);
	if (res != VK_SUCCESS) {
		vkDestroyDescriptorPool(device, dp, nullptr);
		std::cout << "vkAllocateDescriptorSets error" << std::endl;
	}
	return (S_结构对象*)ds;
}

void f_df_releaseDescriptorSet(S_设备环境& ctx, S_结构对象* layout) {
	
}








